﻿package statemachine 
{
	import flash.geom.Point;
	import flash.utils.Dictionary;
	/**
	 * Реализация машины состояний
	 * @author vkozhaev
	 */
	public class StateMachine
	{
			 
		
		private var _conditionsChecker:IConditionsChecker;
		private var _transitions:Dictionary;
		private var _statesFactory:IStatesFactory;
		public function StateMachine() 
		{
			
			_transitions = new Dictionary();
			
		
		}
		
		public function set conditionsChecker(val:IConditionsChecker):void {
			this._conditionsChecker=val
		}
		
		/**
		 * Добавление перехода
		 * @param	stateName состояние
		 * @param	ruleName имя правила
		 * @param	newStateName новое состояние
		 */
		public function setTransition(stateName:String, ruleName:String,newStateName:String):void {
		
			var transitionsArray:Vector.<Object> = _transitions[stateName];
			if (transitionsArray == null) {
				transitionsArray = new Vector.<Object>();
				
			}
			
			transitionsArray.push({'ruleName':ruleName,'newStateName':newStateName})
			_transitions[stateName] = transitionsArray;
		}
		
		/**
		 * Обработка состояния
		 * @param	state
		 * @param	parameters
		 */
		public function processState(stateObject:IStateObject):void {	
			var state:IState = stateObject.state;
			
			if (state.ticks != 0) {//Холостой ход
				state.ticks--;
				state.doInProcess();
				return;
			}
			
			var transitionsArray:Vector.<Object> = _transitions[state.name];
			
			
			if (transitionsArray == null || transitionsArray.length == 0) {//Терминальное состояние
				state.doAfter();
				return;
			}
			
			for each(var obj:Object in transitionsArray) {
				
				var rule:Function = _conditionsChecker.getCondition(obj.ruleName);
				
				var condition:Boolean = rule(stateObject);
				
				if (condition) {
					state.doAfter();
					
					stateObject.state = _statesFactory.makeNewState(stateObject, obj.newStateName);
					stateObject.state.doBefore();
					return;
				}
			}		
		
		}
		
		public function set statesFactory(val:IStatesFactory):void {
			this._statesFactory = val;
		}
	}
}